﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IWMAG.Scripting.AST.ObjectModel;
using IWMAG.Scripting.Types;
using IWMAG.Scripting.Interpreter;
using IWMAG.Scripting.Compiler.UserInfo;

namespace IWMAG.Scripting.AST.Operators {
    internal class TertOperator : CodeExpression {
        public CodeExpression Expr;
        public CodeExpression Then;
        public CodeExpression Else;

        public TertOperator(Compiler.Lexeme l, CodeExpression expr, CodeExpression then, CodeExpression els) : base(l) {
            Expr = expr;
            Then = then;
            Else = els;
        }

        public override void Verify(Helpers.CompileTable sym, List<Compiler.IUserInfo> error) {
            Expr.Verify(sym, error);
            Then.Verify(sym, error);
            Else.Verify(sym, error);

            if (Expr.TypeOf() != CodeType.Bool) {
                SendError(error, Rules.TernaryOperatorFirstArgumentMustBeBool);
            }

            if (Then.TypeOf() != Else.TypeOf()) {
                SendError(error,Rules.TernaryOperatorResultArgumentsOfIncompatibleType);
            }
        }

        public override CodeType TypeOf() {
            return Then.TypeOf();
        }

        public override IEnumerable<Continuation> ValueOf(Interpreter.ScriptEngine engine, Helpers.RuntimeTable sym, Interpreter.Reference<Interpreter.RunValue> val) {
            Reference<RunValue> cond = RunValue.NoValue;
            foreach (Continuation wait in Expr.ValueOf(engine, sym, cond)) yield return wait;
            foreach (Continuation wait in (cond.ReferencedValue.BoolValue ? Then : Else).ValueOf(engine, sym, val)) yield return wait;
        }
    }
}
